package com.sdk.service.impl;

import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.coment.dto.ApiNotify;
import com.coment.dto.LiveData;
import com.coment.dto.LiveData.ApiType;
import com.coment.enums.ApiPushType;
import com.coment.enums.Camp;
import com.coment.enums.PushType;
import com.coment.po.Game;
import com.coment.po.UserInfo;
import com.sdk.config.DYConfig;
import com.sdk.config.TokenConfig;
import com.sdk.utill.HttpUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.io.PrintStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

@Slf4j
@Service
public class DYServiceImpl {
   
   private final Lock $lock = new ReentrantLock();
   @Value("${spring.application.env}")
   private String env;

   private static List<Map<String, Object>> getMaps(Camp camp, List<UserInfo> sortedUsers) {
      List<Map<String, Object>> userList = new ArrayList<>();

      for(int i = 0; i < sortedUsers.size(); ++i) {
         UserInfo userInfo = sortedUsers.get(i);
         Map<String, Object> obj = new HashMap<>();
         obj.put("open_id", userInfo.getUId());
         obj.put("rank", i + 1);
         boolean result = camp.getValue().equals(userInfo.getUserExtends().getContingent());
         obj.put("round_result", result ? 1 : 2);
         obj.put("score", userInfo.getUserExtends().getScore());
         obj.put("winning_points", 0);
         obj.put("winning_streak_count", 0);
         obj.put("group_id", userInfo.getUserExtends() != null ? userInfo.getUserExtends().getContingent() : "");
         userList.add(obj);
      }

      return userList;
   }

   private static List<Map<String, Object>> getMaps(String camp) {
      List<Map<String, Object>> groupResultList = new ArrayList();

      for(Camp value : Camp.values()) {
         if (!value.getValue().isEmpty()) {
            Map<String, Object> elem = new HashMap();
            elem.put("group_id", camp);
            if (value.getValue().equals(camp)) {
               elem.put("result", 1);
            }

            elem.put("result", 2);
            groupResultList.add(elem);
         }
      }

      return groupResultList;
   }

   public List<ApiNotify> parseDouyin(String roomId, String msgType, String body) {
      List<ApiNotify> list = new ArrayList<>();
      PushType pushType = ApiPushType.fromToPushType(msgType);
      switch (pushType) {
         case content:
            List<LiveData.DyPayload.CommentsMsg> commentsMsgList = JSONUtil.toList(body, LiveData.DyPayload.CommentsMsg.class);
            list = commentsMsgList.stream().map(ApiNotify::new).toList();
            log.debug("收到评论消息: {}", list);
            break;
         case gift:
            List<LiveData.DyPayload.LiveGiftMsg> liveGiftMsgList = JSONUtil.toList(body, LiveData.DyPayload.LiveGiftMsg.class);
            list = liveGiftMsgList.stream().map(ApiNotify::new).toList();
            log.debug("收到礼物消息: {}", list);
            break;
         case like:
            List<LiveData.DyPayload.LiveLikeMsg> liveLikeMsgList = JSONUtil.toList(body, LiveData.DyPayload.LiveLikeMsg.class);
            list = liveLikeMsgList.stream().map(ApiNotify::new).toList();
            log.debug("收到点赞消息: {}", list);
            break;
         case fansclub:
            List<LiveData.DyPayload.FansClubMsg> fansClubMsgList = JSONUtil.toList(body, LiveData.DyPayload.FansClubMsg.class);
            list = fansClubMsgList.stream().map(ApiNotify::new).toList();
            log.debug("收到粉丝团消息: {}", list);
      }

      list.forEach((apiNotify) -> {
         apiNotify.setApiType(ApiType.douyin);
         apiNotify.setRoomId(roomId);
      });
      return list;
   }

   public void getAccessToken() {
      TokenConfig.dy_token = "";
      int count = 0;

      while("".equals(TokenConfig.dy_token) || TokenConfig.dy_token.isEmpty() && count == 3) {
         try {
            Map<String, String> params = new HashMap();
            params.put("grant_type", "client_credential");
            params.put("appid", DYConfig.appId);
            params.put("secret", DYConfig.secret);
            String response = HttpUtil.sendPost("https://developer.toutiao.com/api/apps/v2/token", JSON.toJSONString(params), null);
            JSONObject jsonObject = JSON.parseObject(response);
            if (jsonObject == null) {
               continue;
            }

            int errNo = jsonObject.getIntValue("err_no");
            String errTips = jsonObject.getString("err_tips");
            if (errNo != 0 || errTips == null) {
               log.error("获取token时出现异常,错误码：{},错误信息：{},进行第{}次重试", errNo, errTips, count);
               continue;
            }

            JSONObject dataObject = jsonObject.getJSONObject("data");
            String accessToken = dataObject.getString("access_token");
            log.info("accessToken:{}", accessToken);
            TokenConfig.dy_token = accessToken;
         } catch (Exception e) {
            log.error("获取token时出现异常:{},进行第{}次重试", e.getMessage(), count + 1);
            continue;
         } finally {
            ++count;
         }

         return;
      }

   }

   public LiveData.DyPayload.AnchorInfo getRoomId(String token) {
      Map<String, String> params = new HashMap();
      params.put("token", token);
      HashMap<String, String> handers = new HashMap();
      handers.put("X-Token", TokenConfig.dy_token);
      String response = HttpUtil.sendPost("http://webcast.bytedance.com/api/webcastmate/info", JSON.toJSONString(params), handers);
      JSONObject jsonObject = JSON.parseObject(response);
      if (jsonObject != null) {
         int errcode = jsonObject.getIntValue("errcode");
         String errmsg = jsonObject.getString("errmsg");
         if (errcode == 0 && errmsg == null) {
            JSONObject dataObject = jsonObject.getJSONObject("data");
            LiveData.DyPayload.AnchorInfo info = dataObject.getObject("info", LiveData.DyPayload.AnchorInfo.class);
            log.info("主播信息：{}", info);
            return info;
         }

         log.error("获取主播信息的时候出现异常，错误码：{}，错误信息：{}", errcode, errmsg);
      }

      return null;
   }

   public boolean bind(String roomId, boolean isBind) {
      Map<String, String> params = new HashMap();
      params.put("roomid", roomId);
      params.put("appid", DYConfig.appId);
      params.put("msg_type", "");
      HashMap<String, String> handlers = new HashMap();
      handlers.put("access-token", TokenConfig.dy_token);

      for(String msgType : DYConfig.pushTypeList) {
         params.put("msg_type", msgType);
         String url = isBind ? "https://webcast.bytedance.com/api/live_data/task/start" : "https://webcast.bytedance.com/api/live_data/task/stop";
         String response = HttpUtil.sendPost(url, JSON.toJSONString(params), handlers);
         if (response == null) {
            log.info("开启抖音推送失败，返回的主体：{}", response);
            return false;
         }

         JSONObject jsonObject = JSON.parseObject(response);
         int errNo = jsonObject.getIntValue("err_no");
         String errMsg = jsonObject.getString("err_msg");
         if (errNo != 0) {
            log.info("开启抖音推送失败，错误码：{}，错误信息：{}", errNo, errMsg);
            return false;
         }
      }

      return true;
   }

   public void syncRoundStatus(int roundId, String roomId, String anchorOpenId, long time, String camp, int status) {
      Map<String, Object> params = new HashMap();
      params.put("anchor_open_id", anchorOpenId);
      params.put("app_id", DYConfig.appId);
      params.put("room_id", roomId);
      params.put("round_id", roundId);
      params.put("start_time", time);
      params.put("status", status);
      if (status == 2) {
         List<Map<String, Object>> groupResultList = getMaps(camp);
         params.put("group_result_list", groupResultList);
         params.put("end_time", System.currentTimeMillis());
      }

      String response = HttpUtil.sendPost("https://webcast.bytedance.com/api/gaming_con/round/sync_status", JSON.toJSONString(params), this.getRequestHeaders());
      PrintStream var10000 = System.out;
      String var10001 = String.valueOf(params);
      var10000.println("开启/关闭对局请求体：" + var10001 + "\n响应体：" + response);
      if (response != null) {
         JSONObject jsonObject = JSON.parseObject(response);
         int errNo = jsonObject.getIntValue("errcode");
         if (errNo != 0) {
            log.error("开启/关闭对局失败：" + jsonObject.getString("errmsg"));
         }
      }

   }

   public void uploadRoundData(String camp, String uId, String roomId, long roundId) {
      Map<String, Object> params = new HashMap();
      params.put("app_id", DYConfig.appId);
      params.put("group_id", camp);
      params.put("open_id", uId);
      params.put("room_id", roomId);
      params.put("round_id", roundId);
      String response = HttpUtil.sendPost("https://webcast.bytedance.com/api/gaming_con/round/upload_user_group_info", JSON.toJSONString(params), this.getRequestHeaders());
      PrintStream var10000 = System.out;
      String var10001 = String.valueOf(params);
      var10000.println("上报阵营数据请求体：" + var10001 + "\n响应体：" + response);
      if (response != null) {
         JSONObject jsonObject = JSON.parseObject(response);
         int errNo = jsonObject.getIntValue("errcode");
         if (errNo != 0) {
            log.error("上报阵营数据失败：" + jsonObject.getString("errmsg"));
         }
      } else {
         log.error("上报阵营数据失败，响应为空");
      }

   }

   public Object queryViewerCampData(String appId, String uId, String roomId, Game game) {
      return null;
   }

   public Object chooseViewerCamp(String appId, String uId, String roomId, String groupId, String avatarUrl, String nickname, Game game) {
      return null;
   }

   public void uploadRoundRankList(String roomId, Camp camp, Game game) {
   }

   public void uploadUserRoundResult(String roomId, Camp camp, Game game) {
   }

   public void completeUserRoundDataUpload(String roomId, LiveData.DyPayload.AnchorInfo anchorInfo) {
      Map<String, Object> params = new HashMap();
      if (anchorInfo == null) {
         log.warn("房间号：{},上传数据异常", roomId);
      } else {
         params.put("anchor_open_id", anchorInfo.getAnchorOpenId());
         params.put("app_id", DYConfig.appId);
         params.put("room_id", roomId);
         params.put("round_id", anchorInfo.getRoundId());
         params.put("complete_time", System.currentTimeMillis());
         String response = HttpUtil.sendPost("https://webcast.bytedance.com/api/gaming_con/round/complete_upload_user_result", JSON.toJSONString(params), this.getRequestHeaders());
         if (response != null) {
            JSONObject jsonObject = JSON.parseObject(response);
            int errNo = jsonObject.getIntValue("errcode");
            if (errNo != 0) {
               log.error("完成上报本局所有数据失败：" + jsonObject.getString("errmsg"));
            }
         } else {
            log.error("完成上报本局所有数据失败，响应为空");
         }

      }
   }

   public void setWorldRankingVersion() {
      Map<String, Object> params = new HashMap();
      params.put("app_id", DYConfig.appId);
      params.put("is_online_version", this.env.equals("online"));
      params.put("world_rank_version", DYConfig.version);
      System.out.println("请求体：" + params);
      String response = HttpUtil.sendPost("https://webcast.bytedance.com/api/gaming_con/world_rank/set_valid_version", JSON.toJSONString(params), this.getRequestHeaders());
      if (response != null) {
         JSONObject jsonObject = JSON.parseObject(response);
         if (jsonObject.containsKey("errcode")) {
            int errcode = jsonObject.getIntValue("errcode");
            if (errcode != 0 && jsonObject.containsKey("errmsg")) {
               log.error("上传世界榜版本失败,{}", jsonObject.getString("errmsg"));
            }
         }
      }

   }

   public void uploadWorldRankingList(List<UserInfo> weekScore) {
      Map<String, Object> params = new HashMap();
      params.put("app_id", DYConfig.appId);
      params.put("is_online_version", this.env.equals("online"));
      params.put("world_rank_version", DYConfig.version);
      params.put("rank_list", "上传的数据");
      System.out.println("请求体：" + params);

      try {
         List<Object> list = new ArrayList();

         for(int i = 0; i < weekScore.size(); ++i) {
            if (i == 150) {
               return;
            }

            Map<String, Object> obj = new HashMap();
            obj.put("open_id", weekScore.get(i).getUId());
            obj.put("rank", i + 1);
            obj.put("score", weekScore.get(i).getUserExtends().getScore());
            obj.put("winning_streak_count", 0);
            obj.put("winning_points", 0);
            list.add(obj);
         }

         params.put("rank_list", list);
         String response = HttpUtil.sendPost("https://webcast.bytedance.com/api/gaming_con/world_rank/upload_rank_list", JSON.toJSONString(params), this.getRequestHeaders());
         if (response != null) {
            JSONObject jsonObject = JSON.parseObject(response);
            if (jsonObject.containsKey("errcode")) {
               int errcode = jsonObject.getIntValue("errcode");
               if (errcode != 0 && jsonObject.containsKey("errmsg")) {
                  log.error("上传世界榜列表失败,{}", jsonObject.getString("errmsg"));
               }
            }
         }
      } catch (Exception e) {
         log.error("上传世界榜列表失败,", e);
      }

   }

   public void uploadWorldRankingUserResult(List<UserInfo> weekScore) {
      this.$lock.lock();

      try {
         Map<String, Object> params = new HashMap();
         params.put("app_id", DYConfig.appId);
         params.put("is_online_version", this.env.equals("online"));
         params.put("world_rank_version", DYConfig.version);
         params.put("user_list", "上传的数据");
         System.out.println("请求体：" + params);

         try {
            if (weekScore != null && !weekScore.isEmpty()) {
               List<Object> list = new ArrayList();

               for(int i = 0; i < weekScore.size(); ++i) {
                  Map<String, Object> obj = new HashMap();
                  obj.put("open_id", weekScore.get(i).getUId());
                  obj.put("rank", i + 1);
                  obj.put("score", weekScore.get(i).getUserExtends().getScore());
                  obj.put("winning_streak_count", 0);
                  obj.put("winning_points", 0);
                  list.add(obj);
               }

               int count = (weekScore.size() + 49) / 50;

               for(int i = 0; i < count; ++i) {
                  int fromIndex = i * 50;
                  int toIndex = Math.min(50 + i * 50, list.size());
                  params.put("user_list", list.subList(fromIndex, toIndex));
                  HttpUtil.sendPost("https://webcast.bytedance.com/api/gaming_con/world_rank/upload_user_result", JSON.toJSONString(params), this.getRequestHeaders());
               }

               this.completeWorldRankingUpload();
               return;
            }

            log.warn("暂无榜单信息！");
         } catch (Exception e) {
            log.error("上传世界榜所有数据失败：", e);
         }
      } finally {
         this.$lock.unlock();
      }

   }

   public void completeWorldRankingUpload() {
      Map<String, Object> params = new HashMap();
      params.put("app_id", DYConfig.appId);
      params.put("is_online_version", this.env.equals("online"));
      params.put("world_rank_version", DYConfig.version);
      params.put("complete_time", System.currentTimeMillis());
      System.out.println("请求体：" + params);
      String response = HttpUtil.sendPost("https://webcast.bytedance.com/api/gaming_con/world_rank/complete_upload_user_result", JSON.toJSONString(params), this.getRequestHeaders());
      if (response != null) {
         JSONObject jsonObject = JSON.parseObject(response);
         if (jsonObject.containsKey("errcode")) {
            int errcode = jsonObject.getIntValue("errcode");
            if (errcode != 0 && jsonObject.containsKey("errmsg")) {
               log.error("完成上传世界榜版本失败,{}", jsonObject.getString("errmsg"));
            }
         }
      }

   }

   private Map<String, String> getRequestHeaders() {
      Map<String, String> headers = new HashMap();
      headers.put("content-type", "application/json");
      headers.put("X-Token", TokenConfig.dy_token);
      return headers;
   }
}
